#pragma once
class Digit;

#include <list>
#include <vector>
#include <string>

class BigInteger
{
	public:
		BigInteger(){};
		BigInteger(const BigInteger& i_other);
		BigInteger(const std::string& i_str) throw (const std::string&);
		BigInteger& operator = (const BigInteger& i_other);
		BigInteger& operator = (const std::string& i_str) throw (const std::string&);
		BigInteger operator + (const BigInteger& i_other);
		BigInteger operator - (const BigInteger& i_other);
		BigInteger operator * (const BigInteger& i_other);
		BigInteger operator / (const BigInteger& i_other);
		bool operator == (const BigInteger& i_other) const; 
		bool operator < (const BigInteger& i_other) const;
		bool operator > (const BigInteger& i_other) const;
		bool operator != (const BigInteger& i_other) const;
		friend std::ostream& operator << (std::ostream& i_os, const BigInteger& i_this);
	private:
		class Number
		{
			public:
				Number(){};
				Number(const std::string& i_str) throw (const std::string&);
				Number& operator = (const Number& i_other);
				Number& operator = (const std::string& i_str) throw (const std::string&);
				Number& operator = (std::list<Digit>& i_list);
				Number operator + (const Number& i_other);
		        Number operator - (const Number& i_other);
				Number operator * (const Number& i_other);
				Number operator / (const Number& i_other);
				Number operator -() const;
				bool operator == (const Number& i_other) const; 
				bool operator < (const Number& i_other) const;
				bool operator > (const Number& i_other) const;
				bool operator != (const Number& i_other) const;
				std::string GetStr() const;
			private:
				std::vector<Digit> p_PlusVector(const std::vector<Digit>& i_vec) const; 
				std::vector<Digit> p_MinusVector(const std::vector<Digit>& i_vec) const;
				void p_AddDigit(const int& amount, const int& i_digit);
				Number p_GetPiece(const int& i_length);
			private:
				std::vector<Digit> m_vec_number;
				bool m_if_negative;
		};		
		Number m_number;
};

class Digit
{
	public:
		Digit(){};
		Digit(const int& i_value) throw (const std::string&);
		Digit& operator = (const char& i_char) throw (const std::string&);
		Digit& operator = (const int& i_int) throw (const std::string&);
		friend std::ostream& operator << (std::ostream& i_os, const Digit& i_this);
		operator int() const {return mp_digit;}
	private:
		int mp_digit;
};